require "import"
import "android.app.*"
import "android.os.*"
import "android.widget.*"
import "android.view.*"
import "android.media.*"
import "android.content.*"
import "android.database.*"
import "android.net.*"
import "android.provider.*"
import "java.io.*"
import "java.lang.*"
import "com.androlua.*"
import "android.speech.tts.*"

context = activity or service
activity.setTitle("Music Player, created by. sushil rathore")
Toast.makeText(context, "Welcome. Please select a song to play", Toast.LENGTH_SHORT).show()

local textToSpeech
local mediaPlayer = MediaPlayer()
local songList = {}
local songTitles = {}
local currentSongIndex = 1
local audioManager = context.getSystemService(Context.AUDIO_SERVICE)
local handler = Handler()
local stopTimerRunnable = nil
local isTimerSet = false
local autoPlayEnabled = false
local isRepeating = false
local lastPlaybackPosition = 0
local isFullVolume = false

local function initializeTextToSpeech()
  textToSpeech = TextToSpeech(activity, TextToSpeech.OnInitListener {
    onInit = function(status)
      if status == TextToSpeech.SUCCESS then
        textToSpeech.setLanguage(Locale.US)
      end
    end
  })
end

local function speak(text)
  if textToSpeech then
    textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, nil, nil)
  end
end

local function loadMusicFiles()
  local projection = {
    MediaStore.Audio.Media._ID,
    MediaStore.Audio.Media.DATA,
    MediaStore.Audio.Media.TITLE,
    MediaStore.Audio.Media.DATE_ADDED,
    MediaStore.Audio.Media.SIZE,
    MediaStore.Audio.Media.DURATION,
    MediaStore.Audio.Media.ARTIST,
    MediaStore.Audio.Media.ALBUM
  }
  local uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
  local cursor = context.getContentResolver().query(uri, projection, MediaStore.Audio.Media.IS_MUSIC .. "!= 0", nil, nil)

  if cursor ~= nil then
    while cursor.moveToNext() do
      local id = cursor.getString(0)
      local data = cursor.getString(1)
      local title = cursor.getString(2)
      local dateAdded = cursor.getLong(3) * 1000 
      local size = cursor.getLong(4)
      local duration = cursor.getLong(5)
      local artist = cursor.getString(6)
      local album = cursor.getString(7)
      local fullTitle = title .. "" .. data:match("^.+(%..+)$")
      table.insert(songList, {id = id, path = data, title = fullTitle, duration = duration, artist = artist, album = album, dateAdded = dateAdded, size = size})
      table.insert(songTitles, title)
    end
    cursor.close()
  else
    Toast.makeText(context, "No music files found.", Toast.LENGTH_SHORT).show()
  end
end

local function playSong(index, startPosition)
  local song = songList[index]
  if song then
    mediaPlayer.reset()
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC)
    pcall(function()
      mediaPlayer.setDataSource(song.path)
      mediaPlayer.prepare()
      if startPosition then
        mediaPlayer.seekTo(startPosition)
      end
      mediaPlayer.start()
      updateStatusTextView("Playing: " .. song.title)
      audioSlider.setMax(mediaPlayer.getDuration())
      totalDuration = mediaPlayer.getDuration()
      seekBar.setMax(totalDuration)
      updateHandler.post(DelayedRunnable)
    end, function(err)
      local errorMsg = "Error playing song: " .. debug.traceback(err)
      playSong(currentSongIndex, 0)
    end)
  else
    playSong(currentSongIndex, 0)
  end
end

mediaPlayer.setOnErrorListener(MediaPlayer.OnErrorListener{
  onError = function(mp, what, extra)
    local errorMsg = "Media Player Error: " .. what .. ", " .. extra
    playSong(currentSongIndex, 0)
    return true
  end
})

mediaPlayer.setOnCompletionListener(MediaPlayer.OnCompletionListener{
  onCompletion = function(mp)
    if isRepeating then
      playSong(currentSongIndex, 0)
    else
      currentSongIndex = currentSongIndex + 1
      if currentSongIndex > #songList then
        currentSongIndex = 1
      end
      if autoPlayEnabled then
        playSong(currentSongIndex, 0)
      end
    end
  end
})

local layout = LinearLayout(context)
layout.setOrientation(LinearLayout.VERTICAL)

-- UI Elements:
local statusTextView = TextView(context)
local totalSongsTextView = TextView(context)
local searchEditText = EditText(context)
local searchButton = Button(context)
local volumeLabel = TextView(context)
local volumeSlider = SeekBar(context)
local adjustAudioTextView = TextView(context)
local seekBar = SeekBar(context)
local currentTimeTextView = TextView(context)
local totalTimeTextView = TextView(context)
local sortSpinner = Spinner(context)
local songListView = ListView(context)
local buttonSize = 5

-- Set text for UI elements:
statusTextView.setText("Select a song to play")
totalSongsTextView.setText("Loading songs...")
searchEditText.setHint("Search for songs and audio files")
searchButton.setText("Search")
volumeLabel.setText("Adjust Volume Slider")
adjustAudioTextView.setText("Adjust audio Slider")

-- Set layout parameters for UI elements:
statusTextView.setLayoutParams(LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT))
totalSongsTextView.setLayoutParams(LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT))
searchEditText.setLayoutParams(LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT))
searchButton.setLayoutParams(LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, buttonSize))
volumeLabel.setLayoutParams(LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT))
volumeSlider.setLayoutParams(LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT))
adjustAudioTextView.setLayoutParams(LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT))
seekBar.setLayoutParams(LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT))
currentTimeTextView.setLayoutParams(LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT))
totalTimeTextView.setLayoutParams(LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT))
sortSpinner.setLayoutParams(LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT))

-- Add UI elements to the layout:
layout.addView(statusTextView)
layout.addView(totalSongsTextView)
layout.addView(searchEditText)
layout.addView(searchButton)
layout.addView(volumeLabel)
layout.addView(volumeSlider)
layout.addView(adjustAudioTextView)
layout.addView(seekBar)
layout.addView(currentTimeTextView)
layout.addView(totalTimeTextView)
layout.addView(sortSpinner)

-- Create a horizontal linear layout for the control buttons
local controlLayout = LinearLayout(context)
controlLayout.setOrientation(LinearLayout.HORIZONTAL)
controlLayout.setLayoutParams(LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT))

-- Add control buttons to the controlLayout
local stopButton = Button(context)
stopButton.setText("STOP")
stopButton.setLayoutParams(LinearLayout.LayoutParams(0, buttonSize, 1))
controlLayout.addView(stopButton)

local stButton = Button(context)
stButton.setText("RESTART SONG")
stButton.setLayoutParams(LinearLayout.LayoutParams(0, buttonSize, 1))
controlLayout.addView(stButton)

local rewindButton = Button(context)
rewindButton.setText("REWIND 10 SECONDS")
rewindButton.setLayoutParams(LinearLayout.LayoutParams(0, buttonSize, 1))
controlLayout.addView(rewindButton)

local previousButton = Button(context)
previousButton.setText("PREVIOUS")
previousButton.setLayoutParams(LinearLayout.LayoutParams(0, buttonSize, 1))
controlLayout.addView(previousButton)

local playPauseButton = Button(context)
playPauseButton.setText("PLAY")
playPauseButton.setLayoutParams(LinearLayout.LayoutParams(0, buttonSize, 1))
controlLayout.addView(playPauseButton)

local pauseButton = Button(context)
pauseButton.setText("PAUSE")
pauseButton.setLayoutParams(LinearLayout.LayoutParams(0, buttonSize, 1))
controlLayout.addView(pauseButton)

local nextButton = Button(context)
nextButton.setText("NEXT")
nextButton.setLayoutParams(LinearLayout.LayoutParams(0, buttonSize, 1))
controlLayout.addView(nextButton)

local fastForwardButton = Button(context)
fastForwardButton.setText("FAST FORWARD 10 SECONDS")
fastForwardButton.setLayoutParams(LinearLayout.LayoutParams(0, buttonSize, 1))
controlLayout.addView(fastForwardButton)

-- Speed Control Button
local speedControlButton = Button(context)
speedControlButton.setText("Speed Control")
speedControlButton.setLayoutParams(LinearLayout.LayoutParams(0, buttonSize, 1))
controlLayout.addView(speedControlButton)

-- Auto Play Button
local autoPlayButton = Button(context)
autoPlayButton.setText("Auto Play: off")
autoPlayButton.setLayoutParams(LinearLayout.LayoutParams(0, buttonSize, 1))
controlLayout.addView(autoPlayButton)

-- Shuffle Button
local shuffleButton = Button(context)
shuffleButton.setText("Shuffle")
shuffleButton.setLayoutParams(LinearLayout.LayoutParams(0, buttonSize, 1))
controlLayout.addView(shuffleButton)

-- Repeat Button
local repeatButton = Button(context)
repeatButton.setText("Repeat: Off")
repeatButton.setLayoutParams(LinearLayout.LayoutParams(0, buttonSize, 1))
controlLayout.addView(repeatButton)

-- Full Volume Button
local fullVolumeButton = Button(context)
fullVolumeButton.setText("Switch to Full Volume")
fullVolumeButton.setLayoutParams(LinearLayout.LayoutParams(0, buttonSize, 1))
controlLayout.addView(fullVolumeButton)

-- Add the controlLayout to the main layout
layout.addView(controlLayout)

-- Add the songListView to the main layout
layout.addView(songListView)

-- Set content view:
activity.setContentView(layout)

-- Load music files:
loadMusicFiles()
totalSongsTextView.setText("Total songs available: " .. #songList)

-- Create song list adapter:
local adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, songTitles)
songListView.setAdapter(adapter)

-- Set up sort spinner:
local sortOptions = {
  "sort by New as First",
  "sort by Oldest First",
  "Sort by Title",
  "Sort by Path",
  "Sort by ID",
  "Sort by Date Added",
  "Sort by Duration",
  "Sort by Artist",
  "Sort by Album"
}
local sortAdapter = ArrayAdapter(context, android.R.layout.simple_spinner_item, sortOptions)
sortAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
sortSpinner.setAdapter(sortAdapter)

-- Function to sort songs:
function sortSongs(sortOption)
  if sortOption == "Sort by Title" then
    table.sort(songList, function(a, b) return a.title:lower() < b.title:lower() end)
  elseif sortOption == "Sort by Path" then
    table.sort(songList, function(a, b) return a.path:lower() < b.path:lower() end)
  elseif sortOption == "Sort by ID" then
    table.sort(songList, function(a, b) return a.id < b.id end)
  elseif sortOption == "Sort by Date Added" then
    table.sort(songList, function(a, b) return a.dateAdded < b.dateAdded end)
  elseif sortOption == "Sort by Duration" then
    table.sort(songList, function(a, b) return a.duration < b.duration end)
  elseif sortOption == "Sort by Artist" then
    table.sort(songList, function(a, b) return a.artist:lower() < b.artist:lower() end)
  elseif sortOption == "Sort by Album" then
    table.sort(songList, function(a, b) return a.album:lower() < b.album:lower() end)
  elseif sortOption == "sort by New as First" then
    table.sort(songList, function(a, b) return a.dateAdded > b.dateAdded end)
  elseif sortOption == "sort by Oldest First" then
    table.sort(songList, function(a, b) return a.dateAdded < b.dateAdded end)
  end
  songTitles = {}
  for i, song in ipairs(songList) do
    table.insert(songTitles, song.title)
  end
  adapter.clear()
  adapter.addAll(songTitles)
  adapter.notifyDataSetChanged()
end

-- Set up sort spinner listener:
sortSpinner.setOnItemSelectedListener(AdapterView.OnItemSelectedListener{
  onItemSelected = function(parent, view, position, id)
    local selectedSortOption = sortOptions[position + 1]
    sortSongs(selectedSortOption)
  end,
  onNothingSelected = function(parent)
  end
})

-- Function for play/pause button:
function playPauseButtonClicked()
  if mediaPlayer.isPlaying() then
    mediaPlayer.pause()
    lastPlaybackPosition = mediaPlayer.getCurrentPosition()
    stopUpdateHandler()
    playPauseButton.setText("Play")
    statusTextView.setText("paused: " .. songList[currentSongIndex].title)
  else
    if currentSongIndex > 0 then
      playSong(currentSongIndex, lastPlaybackPosition)
      playPauseButton.setText("Pause")
      statusTextView.setText("Playing: " .. songList[currentSongIndex].title)
    end
  end
end

-- Function for stop button:
function stopButtonClicked()
  if mediaPlayer.isPlaying() then
    mediaPlayer.stop()
    playPauseButton.setText("Play again!")
    statusTextView.setText("stopped: " .. songList[currentSongIndex].title)
  else
    speak("no song is playing")
  end
end

-- Function for restart button:
function stButtonClicked()
  if mediaPlayer.isPlaying() then
    stButton.setText("restart song")
    playSong(currentSongIndex)
  else
    speak("Please play a song first! and Click this button to restart again!")
  end
end

-- Function for shuffle button:
function shuffleButtonClicked()
  local newIndex = math.random(1, #songList)
  if newIndex == currentSongIndex then
    newIndex = newIndex + 1
    if newIndex > #songList then
      newIndex = 1
    end
  end
  currentSongIndex = newIndex
  lastPlaybackPosition = 0
  playSong(currentSongIndex)
  playPauseButton.setText("Pause")
  statusTextView.setText("Playing: " .. songList[currentSongIndex].title)
end

-- Function for next button:
function nextButtonClicked()
  currentSongIndex = currentSongIndex + 1
  if currentSongIndex > #songList then
    currentSongIndex = 1
  end
  lastPlaybackPosition = 0
  playSong(currentSongIndex, lastPlaybackPosition)
end

-- Function for previous button:
function previousButtonClicked()
  currentSongIndex = currentSongIndex - 1
  if currentSongIndex < 1 then
    currentSongIndex = #songList
  end
  lastPlaybackPosition = 0
  playSong(currentSongIndex, lastPlaybackPosition)
end

-- Function for rewind button:
function rewindButtonClicked()
  if mediaPlayer.isPlaying() then
    local currentPosition = mediaPlayer.getCurrentPosition()
    mediaPlayer.seekTo(math.max(0, currentPosition - 10000)) 
  end
end

-- Function for fast forward button:
function fastForwardButtonClicked()
  if mediaPlayer.isPlaying() then
    local currentPosition = mediaPlayer.getCurrentPosition()
    mediaPlayer.seekTo(math.min(mediaPlayer.getDuration(), currentPosition + 10000)) 
  end
end

-- Function for speed control button:
function speedControlButtonClicked()
  local dialogBuilder = AlertDialog.Builder(context)
  local dialogLayout = LinearLayout(context)
  dialogLayout.setOrientation(LinearLayout.VERTICAL)
  local speedSeekBar = SeekBar(context)
  speedSeekBar.setMax(200)
  speedSeekBar.setProgress(100)

  local speedTextView = TextView(context)
  speedTextView.setText("Speed: 1.0x")

  speedSeekBar.setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener{
    onProgressChanged = function(seekBar, progress, fromUser)
      local speed = progress / 100.0
      mediaPlayer.setPlaybackParams(mediaPlayer.getPlaybackParams().setSpeed(speed))
      speedTextView.setText("Speed: " .. string.format("%.1f", speed) .. "x")
    end,
    onStartTrackingTouch = function(seekBar) end,
    onStopTrackingTouch = function(seekBar) end
  })

  dialogLayout.addView(speedTextView)
  dialogLayout.addView(speedSeekBar)
  dialogBuilder.setView(dialogLayout)
  dialogBuilder.setTitle("Adjust Playback Speed")
  dialogBuilder.setPositiveButton("OK", nil)
  dialogBuilder.show()
end

-- Function for auto play button:
function autoPlayButtonClicked()
  autoPlayEnabled = not autoPlayEnabled
  if autoPlayEnabled then
    autoPlayButton.setText("Auto Play: On")
  else
    autoPlayButton.setText("Auto Play: off")
  end
end

-- Function for shuffle button:
function shuffleButtonClicked()
  local newIndex = math.random(1, #songList)
  if newIndex == currentSongIndex then
    newIndex = newIndex + 1
    if newIndex > #songList then
      newIndex = 1
    end
  end
  currentSongIndex = newIndex
  lastPlaybackPosition = 0
  playSong(currentSongIndex)
  playPauseButton.setText("Pause")
  statusTextView.setText("Playing: " .. songList[currentSongIndex].title)
end

-- Function for repeat button:
function repeatButtonClicked()
  isRepeating = not isRepeating
  if isRepeating then
    repeatButton.setText("Repeat: On")
  else
    repeatButton.setText("Repeat: Off")
  end
end

-- Function for full volume button:
function fullVolumeButtonClicked()
  isFullVolume = not isFullVolume
  if isFullVolume then
    audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), AudioManager.FLAG_PLAY_SOUND)
    fullVolumeButton.setText("Switch to Silent")
  else
    audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, AudioManager.FLAG_PLAY_SOUND)
    fullVolumeButton.setText("Switch to Full Volume")
  end
end

-- Function for search button:
function searchButtonClicked()
  local query = searchEditText.getText().toString():lower()
  if query == "" then
    speak("The search text box is empty. Please enter your search query first.")
    return
  end
  local filteredSongs = {}
  local filteredSongIndexes = {}
  for i, song in ipairs(songList) do
    if song.title:lower():find(query) then
      table.insert(filteredSongs, song.title)
      table.insert(filteredSongIndexes, i)
    end
  end
  if #filteredSongs == 0 then
    table.insert(filteredSongs, "No results found")
    speak("No results found")
  else
    speak("Results available, click to play.")
  end
  adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, filteredSongs)
  songListView.setAdapter(adapter)

  local isPlaying = false
  local lastPlaybackPosition = 0

  songListView.setOnItemClickListener(function(parent, view, position, id)
    if #filteredSongIndexes > 0 then
      local selectedSongIndex = filteredSongIndexes[position + 1]
      if isPlaying and currentSongIndex ~= selectedSongIndex then
        mediaPlayer.stop()
        mediaPlayer.reset()
        lastPlaybackPosition = 0
        playPauseButton.setText("Pause")
        updateStatusTextView("Playing: " .. filteredSongs[position + 1])
        isPlaying = false
      end
      if not isPlaying or currentSongIndex ~= selectedSongIndex then
        currentSongIndex = selectedSongIndex
        playSong(currentSongIndex, lastPlaybackPosition)
        playPauseButton.setText("Pause")
        updateStatusTextView("Playing: " .. filteredSongs[position + 1])
        isPlaying = true
      elseif isPlaying and currentSongIndex == selectedSongIndex then
        if mediaPlayer.isPlaying() then
          lastPlaybackPosition = mediaPlayer.getCurrentPosition()
          mediaPlayer.pause()
          playPauseButton.setText("Play")
          updateStatusTextView("Paused: " .. filteredSongs[position + 1])
          isPlaying = false
        else
          mediaPlayer.seekTo(lastPlaybackPosition)
          mediaPlayer.start()
          updateStatusTextView("Playing: " .. filteredSongs[position + 1])
          isPlaying = true
        end
      end
    end
  end)
end

function onPause()
  if not isTimerSet then
    if mediaPlayer.isPlaying() then
      mediaPlayer.stop()
      playPauseButton.setText("Play")
      Toast.makeText(context, "created by Sushil Rathore. Thank you for using, goodbye.", Toast.LENGTH_SHORT).show()
      updateStatusTextView("Stopped")
    end
  end
end

function onStop()
  -- इस फ़ंक्शन को तब उपयोग कर सकते हैं जब आपको activity को बैकग्राउंड में जाने पर कुछ कार्यवाही करनी हो
end

function onDestroy()
  -- इस फ़ंक्शन को तब उपयोग कर सकते हैं जब activity पूरी तरह से समाप्त हो रही हो
end

function onResume()
  if mediaPlayer.isPlaying() then
    updateStatusTextView("Playing: " .. songList[currentSongIndex].title)
    playPauseButton.setText("Pause")
  else
    updateStatusTextView("Select a song to play")
    playPauseButton.setText("Play")
  end
end

-- Function to rename a file
local function renameFile(filePath, newFileName)
  local file = File(filePath)
  if file.exists() then
    local newFilePath = file.getParent() .. "/" .. newFileName .. file.getName():match("^(%..+)$")
    if file.renameTo(File(newFilePath)) then
      Toast.makeText(context, "File renamed successfully!", Toast.LENGTH_SHORT).show()
    else
      Toast.makeText(context, "Failed to rename file.", Toast.LENGTH_SHORT).show()
    end
  else
    Toast.makeText(context, "File does not exist.", Toast.LENGTH_SHORT).show()
  end
end

-- Function to share a file
local function shareFile(filePath)
  local intent = Intent(Intent.ACTION_SEND)
  intent.setType("*/*")
  intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(File(filePath)))
  context.startActivity(Intent.createChooser(intent, "Share File"))
end

-- Function for Long Click on List Item
songListView.setOnItemLongClickListener(AdapterView.OnItemLongClickListener{
  onItemLongClick = function(parent, view, position, id)
    local song = songList[position + 1]
    local songTitle = song.title
    local filePath = song.path

    local options = {
      "File Information",
      "Rename File",
      "Delete Song",
      "Share File"
    }

    local dialog = AlertDialog.Builder(context)
    Toast.makeText(context, "  Select an option", Toast.LENGTH_SHORT).show()
    dialog.setTitle("Select an option")
    dialog.setItems(options, DialogInterface.OnClickListener{
      onClick = function(dialog, which)
        if options[which + 1] == "File Information" then
          Toast.makeText(context, "  File Information", Toast.LENGTH_SHORT).show()
          local aboutDialog = AlertDialog.Builder(context)
          aboutDialog.setTitle("File Information")

          local aboutLayout = LinearLayout(context)
          aboutLayout.setOrientation(LinearLayout.VERTICAL)

          local titleTextView = TextView(context)
          titleTextView.setText("Title: " .. songTitle)
          aboutLayout.addView(titleTextView)

          local pathTextView = TextView(context)
          pathTextView.setText("Path: " .. filePath)
          aboutLayout.addView(pathTextView)

          -- Function to format file size
          local function formatFileSize(size)
            if size >= 1024 * 1024 then
              return string.format("%.2f MB", size / (1024 * 1024))
            elseif size >= 1024 then
              return string.format("%.2f KB", size / 1024)
            else
              return string.format("%d bytes", size)
            end
          end

          local sizeTextView = TextView(context)
          sizeTextView.setText("Size: " .. formatFileSize(song.size))
          aboutLayout.addView(sizeTextView)

          aboutDialog.setView(aboutLayout)
          aboutDialog.setPositiveButton("OK", nil)
          aboutDialog.show()
        elseif options[which + 1] == "Rename File" then
          local renameDialog = AlertDialog.Builder(context)
          renameDialog.setTitle("Rename File")
          local view = View.inflate(context, "layout/rename_dialog", nil)
          local newFileNameInput = view.findViewById(R.id.new_file_name_input)
          renameDialog.setView(view)
          renameDialog.setPositiveButton("Rename", function(dialog, which)
            local newFileName = newFileNameInput.getText().toString()
            renameFile(filePath, newFileName)
          end)
          renameDialog.setNegativeButton("Cancel", function(dialog, which)
            dialog.dismiss()
          end)
          renameDialog.show()
        elseif options[which + 1] == "Delete Song" then
          Toast.makeText(context, " delete", Toast.LENGTH_SHORT).show()
          local deleteDialog = AlertDialog.Builder(context)
          deleteDialog.setTitle("Delete!")
          deleteDialog.setMessage("Are you sure you want to delete " .. songTitle .. "?")
          deleteDialog.setPositiveButton("Delete", function(dialog, which)
            local file = File(filePath)
            if file.exists() and file.delete() then
              table.remove(songList, position + 1)
              table.remove(songTitles, position + 1)
              adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, songTitles)
              songListView.setAdapter(adapter)
              adapter.notifyDataSetChanged()
              Toast.makeText(context, songTitle .. " deleted.", Toast.LENGTH_SHORT).show()
            else
              Toast.makeText(context, "Failed to delete " .. songTitle .. ".", Toast.LENGTH_SHORT).show()
            end
          end)
          deleteDialog.setNegativeButton("Cancel", function(dialog, which)
            dialog.dismiss()
            Toast.makeText(context, " canceld", Toast.LENGTH_SHORT).show()
          end)
          deleteDialog.show()
        elseif options[which + 1] == "Share File" then
          shareFile(filePath)
        end
      end
    })
    dialog.show()
    return true
  end
})

-- Function to set stop timer:
local function setStopTimer(hours, minutes, seconds)
  if stopTimerRunnable then
    handler.removeCallbacks(stopTimerRunnable)
  end
  local delay = (hours * 3600 + minutes * 60 + seconds) * 1000
  stopTimerRunnable = Runnable({
    run = function()
      if mediaPlayer.isPlaying() then
        mediaPlayer.stop()
        stopTimerRunnable = nil
        isTimerSet = false
        Toast.makeText(context, "Timer stopped the music", Toast.LENGTH_SHORT).show()
      end
    end
  })
  handler.postDelayed(stopTimerRunnable, delay)
  isTimerSet = true
  Toast.makeText(context, "Stop timer set for " .. hours .. " hours " .. minutes .. " minutes " .. seconds .. " seconds", Toast.LENGTH_SHORT).show()
end

-- Function for set timer button:
function setTimerButtonClicked()
  local dialogBuilder = AlertDialog.Builder(context)
  dialogBuilder.setTitle("Set Stop Timer")
  local view = View.inflate(context, "layout/timer_dialog", nil)
  local hoursInput = view.findViewById(R.id.timer_hours_input)
  local minutesInput = view.findViewById(R.id.timer_minutes_input)
  local secondsInput = view.findViewById(R.id.timer_seconds_input)
  dialogBuilder.setView(view)
  dialogBuilder.setPositiveButton("Set", function(dialog, which)
    local hours = tonumber(hoursInput.getText().toString()) or 0
    local minutes = tonumber(minutesInput.getText().toString()) or 0
    local seconds = tonumber(secondsInput.getText().toString()) or 0
    setStopTimer(hours, minutes, seconds)
  end)
  dialogBuilder.setNegativeButton("Cancel", function(dialog, which)
    dialog.dismiss()
  end)
  dialogBuilder.show()
end

-- Function for full volume button:
function fullVolumeButtonClicked()
  isFullVolume = not isFullVolume
  if isFullVolume then
    audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), AudioManager.FLAG_PLAY_SOUND)
    fullVolumeButton.setText("Switch to Silent")
  else
    audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, AudioManager.FLAG_PLAY_SOUND)
    fullVolumeButton.setText("Switch to Full Volume")
  end
end

-- Function for search button:
function searchButtonClicked()
  local query = searchEditText.getText().toString():lower()
  if query == "" then
    speak("The search text box is empty. Please enter your search query first.")
    return
  end
  local filteredSongs = {}
  local filteredSongIndexes = {}
  for i, song in ipairs(songList) do
    if song.title:lower():find(query) then
      table.insert(filteredSongs, song.title)
      table.insert(filteredSongIndexes, i)
    end
  end
  if #filteredSongs == 0 then
    table.insert(filteredSongs, "No results found")
    speak("No results found")
  else
    speak("Results available, click to play.")
  end
  adapter = ArrayAdapter(context, android.R.layout.simple_list_item_1, filteredSongs)
  songListView.setAdapter(adapter)

  local isPlaying = false
  local lastPlaybackPosition = 0

  songListView.setOnItemClickListener(function(parent, view, position, id)
    if #filteredSongIndexes > 0 then
      local selectedSongIndex = filteredSongIndexes[position + 1]
      if isPlaying and currentSongIndex ~= selectedSongIndex then
        mediaPlayer.stop()
        mediaPlayer.reset()
        lastPlaybackPosition = 0
        playPauseButton.setText("Pause")
        updateStatusTextView("Playing: " .. filteredSongs[position + 1])
        isPlaying = false
      end
      if not isPlaying or currentSongIndex ~= selectedSongIndex then
        currentSongIndex = selectedSongIndex
        playSong(currentSongIndex, lastPlaybackPosition)
        playPauseButton.setText("Pause")
        updateStatusTextView("Playing: " .. filteredSongs[position + 1])
        isPlaying = true
      elseif isPlaying and currentSongIndex == selectedSongIndex then
        if mediaPlayer.isPlaying() then
          lastPlaybackPosition = mediaPlayer.getCurrentPosition()
          mediaPlayer.pause()
          playPauseButton.setText("Play")
          updateStatusTextView("Paused: " .. filteredSongs[position + 1])
          isPlaying = false
        else
          mediaPlayer.seekTo(lastPlaybackPosition)
          mediaPlayer.start()
          updateStatusTextView("Playing: " .. filteredSongs[position + 1])
          isPlaying = true
        end
      end
    end
  end)
end

initializeTextToSpeech()
